home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Power 1997 December
/
MACPOWER-1997-12.ISO.7z
/
MACPOWER-1997-12.ISO
/
AMUG
/
PROGRAMMING
/
Raven 1.2.sit
/
Raven 1.2
/
Source
/
Foundation
/
OS
/
ZResUtils.cpp
< prev
next >
Wrap
Text File
|
1997-08-07
|
17KB
|
727 lines
/*
* File: ZResUtils.cpp
* Summary: Resource manager utilities.
* Written by: Jesse Jones
*
* Copyright ゥ 1996-1997 Jesse Jones.
* For conditions of distribution and use, see copyright notice in ZTypes.h
*
* Change History (most recent first):
*
* <2> 4/12/97 JDJ Added GetResourceInfo.
* <1> 2/03/96 JDJ Created
*/
#include <ZResUtils.h>
#include <Errors.h>
#include <LowMem.h>
#include <Resources.h>
#include <Script.h>
#include <SLFunctions.h>
#include <ZDebug.h>
#include <ZExceptions.h>
#include <ZStringUtils.h>
//-----------------------------------
// Constants
//
const ulong kMaxBufferSize = 4*1024L*1024L; // Used for sanity checking
// ===================================================================================
// Helper Functions
// ===================================================================================
//---------------------------------------------------------------
//
// IsPurgeableHand
//
//---------------------------------------------------------------
static bool IsPurgeableHand(Handle hand)
{
ASSERT(hand != nil);
char state = HGetState(hand);
OSErr err = MemError();
if (err == noErr)
return (state & 0x40) != 0;
else if (err == nilHandleErr)
return true; // Handle has been purged.
else
DEBUGSTR("Error %d in IsPurgeable.", err);
return false;
}
//---------------------------------------------------------------
//
// IsResourceHand
//
//---------------------------------------------------------------
static bool IsResourceHand(Handle hand)
{
ASSERT(hand != nil); // Might want to treat this like IsPurgeable.
char state = HGetState(hand);
ASSERT(MemError() == noErr);
return (state & 0x20) != 0;
}
//---------------------------------------------------------------
//
// GetResourceNoLoad (ResType, ResID, bool)
//
//---------------------------------------------------------------
static Handle GetResourceNoLoad(ResType type, ResID id, bool get1)
{
Handle rsrc = nil;
SetResLoad(false);
if (get1)
rsrc = Get1Resource(type, id);
else
rsrc = GetResource(type, id);
OSErr err = ResError();
SetResLoad(true);
return rsrc;
}
//---------------------------------------------------------------
//
// GetResourceNoLoad (ResType, string, bool)
//
//---------------------------------------------------------------
static Handle GetResourceNoLoad(ResType type, const string& inName, bool get1)
{
Handle rsrc = nil;
unsigned char* name = StrToPStr(inName);
SetResLoad(false);
if (get1)
rsrc = Get1NamedResource(type, name);
else
rsrc = GetNamedResource(type, name);
OSErr err = ResError();
SetResLoad(true);
return rsrc;
}
//---------------------------------------------------------------
//
// CreateResource
//
// Creates a resource of the specified size or resizes an existing
// resource.
//
//---------------------------------------------------------------
static Handle CreateResource(ResType type, ResID id, const string& name, ulong size, short attrs)
{
Handle handle = nil;
OSErr err = noErr;
SLDisable(); // Spotlight complains if the resource doesn't exist
if (name.length() > 0)
handle = Get1NamedResource(type, StrToPStr(name));
else
handle = Get1Resource(type, id);
SLEnable();
if (handle == nil) {
handle = NewHandle(size);
ThrowIfMemFail(handle);
if (name.length() > 0)
id = UniqueID(type);
AddResource(handle, type, id, StrToPStr(name));
err = ResError();
if (err == noErr) {
if (attrs != 0)
SetResAttrs(handle, (short) (attrs | resChanged)); // preserve resChanged (it is set by AddResource())
} else {
DisposeHandle(handle);
ThrowIfOSErr(err);
}
} else if (GetHandleSize(handle) != size) {
SetHandleSize(handle, size);
err = MemError();
if (err == noErr) {
ChangedResource(handle);
err = ResError();
if (err != noErr) {
ReleaseIfResource(handle);
ThrowIfOSErr(err);
}
}
} else {
ChangedResource(handle); // Make sure resChanged bit is set.
ThrowIfResError();
}
return handle;
}
#pragma mark -
// ===================================================================================
// Global Functions
// ===================================================================================
//---------------------------------------------------------------
//
// ReadResource (ResType, ResID, void*, ulong)
//
//---------------------------------------------------------------
void ReadResource(ResType type, ResID id, void* buffer, ulong bytes)
{
ASSERT(buffer != nil);
ASSERT(bytes < kMaxBufferSize);
Handle rsrc = GetResourceNoLoad(type, id, false);
ThrowIfResFail(rsrc);
long handleSize = GetResourceSizeOnDisk(rsrc);
ASSERT(ResError() == noErr && handleSize >= bytes);
ReadPartialResource(rsrc, 0, buffer, (long) bytes);
OSErr err = ResError();
ReleaseResource(rsrc);
ThrowIfOSErr(err);
}
//---------------------------------------------------------------
//
// ReadResource (ResType, string, void*, ulong)
//
//---------------------------------------------------------------
void ReadResource(ResType type, const string& name, void* buffer, ulong bytes)
{
ASSERT(buffer != nil);
ASSERT(bytes < kMaxBufferSize);
Handle rsrc = GetResourceNoLoad(type, name, false);
ThrowIfResFail(rsrc);
long handleSize = GetResourceSizeOnDisk(rsrc);
ASSERT(ResError() == noErr && handleSize >= bytes);
ReadPartialResource(rsrc, 0, buffer, (long) bytes);
OSErr err = ResError();
ReleaseResource(rsrc);
ThrowIfOSErr(err);
}
//---------------------------------------------------------------
//
// Read1Resource (ResType, ResID, void*, ulong)
//
//---------------------------------------------------------------
void Read1Resource(ResType type, ResID id, void* buffer, ulong bytes)
{
ASSERT(buffer != nil);
ASSERT(bytes < kMaxBufferSize);
Handle rsrc = GetResourceNoLoad(type, id, true);
ThrowIfResFail(rsrc);
long handleSize = GetResourceSizeOnDisk(rsrc);
ASSERT(ResError() == noErr && handleSize >= bytes);
ReadPartialResource(rsrc, 0, buffer, (long) bytes);
OSErr err = ResError();
ReleaseResource(rsrc);
ThrowIfOSErr(err);
}
//---------------------------------------------------------------
//
// Read1Resource (ResType, string, void*, ulong)
//
//---------------------------------------------------------------
void Read1Resource(ResType type, const string& name, void* buffer, ulong bytes)
{
ASSERT(buffer != nil);
ASSERT(bytes < kMaxBufferSize);
Handle rsrc = GetResourceNoLoad(type, name, true);
ThrowIfResFail(rsrc);
long handleSize = GetResourceSizeOnDisk(rsrc);
ASSERT(ResError() == noErr && handleSize >= bytes);
ReadPartialResource(rsrc, 0, buffer, (long) bytes);
OSErr err = ResError();
ReleaseResource(rsrc);
ThrowIfOSErr(err);
}
//---------------------------------------------------------------
//
// WriteResource (ResType, ResID, Handle, bool)
//
//---------------------------------------------------------------
void WriteResource(ResType type, ResID id, Handle data, bool purgeable)
{
ASSERT(data != nil && *data != nil);
ASSERT(!IsPurgeableHand(data));
short attrs = 0;
if (purgeable)
attrs += resPurgeable;
ulong size = (ulong) GetHandleSize(data);
Handle rsrc = CreateResource(type, id, "", size, attrs);
BlockMoveData(*data, *rsrc, size);
WriteResource(rsrc);
ThrowIfResError();
ReleaseIfResource(rsrc);
}
//---------------------------------------------------------------
//
// WriteResource (ResType, string, Handle, bool)
//
//---------------------------------------------------------------
void WriteResource(ResType type, const string& name, Handle data, bool purgeable)
{
ASSERT(data != nil && *data != nil);
ASSERT(!IsPurgeableHand(data));
short attrs = 0;
if (purgeable)
attrs += resPurgeable;
ulong size = (ulong) GetHandleSize(data);
Handle rsrc = CreateResource(type, 0, name, size, attrs);
BlockMoveData(*data, *rsrc, size);
WriteResource(rsrc);
ThrowIfResError();
ReleaseIfResource(rsrc);
}
//---------------------------------------------------------------
//
// WriteResource (ResType, ResID, const void*, ulong, bool)
//
//---------------------------------------------------------------
void WriteResource(ResType type, ResID id, const void* buffer, ulong bytes, bool purgeable)
{
ASSERT(buffer != nil);
ASSERT(bytes < kMaxBufferSize);
short attrs = 0;
if (purgeable)
attrs += resPurgeable;
Handle rsrc = CreateResource(type, id, "", bytes, attrs);
BlockMoveData(buffer, *rsrc, bytes);
WriteResource(rsrc);
ThrowIfResError();
ReleaseIfResource(rsrc);
}
//---------------------------------------------------------------
//
// WriteResource (ResType, string, const void*, ulong, bool)
//
//---------------------------------------------------------------
void WriteResource(ResType type, const string& name, const void* buffer, ulong bytes, bool purgeable)
{
ASSERT(buffer != nil);
ASSERT(bytes < kMaxBufferSize);
short attrs = 0;
if (purgeable)
attrs += resPurgeable;
Handle rsrc = CreateResource(type, 0, name, bytes, attrs);
BlockMoveData(buffer, *rsrc, bytes);
WriteResource(rsrc);
ThrowIfResError();
ReleaseIfResource(rsrc);
}
//---------------------------------------------------------------
//
// Delete1Resource (ResType)
//
//---------------------------------------------------------------
void Delete1Resource(ResType type)
{
short num = ::Count1Resources(type);
for (short index = 1; index <= num; index++) {
Handle hand;
{
TNoResLoad noLoad;
hand = ::Get1IndResource(type, 1);
ThrowIfResFail(hand);
}
::RemoveResource(hand);
ThrowIfResError();
::DisposeHandle(hand);
}
}
//---------------------------------------------------------------
//
// DeleteResource (ResType)
//
//---------------------------------------------------------------
void DeleteResource(ResType type)
{
short num = ::CountResources(type);
for (short index = 1; index <= num; index++) {
Handle hand;
{
TNoResLoad noLoad;
hand = ::GetIndResource(type, 1);
ThrowIfResFail(hand);
}
::RemoveResource(hand);
ThrowIfResError();
::DisposeHandle(hand);
}
}
//---------------------------------------------------------------
//
// DeleteResource (ResType, ResID)
//
//---------------------------------------------------------------
void DeleteResource(ResType type, ResID id)
{
Handle handle = GetResourceNoLoad(type, id, true);
ASSERT(handle != nil);
if (handle != nil) {
short refNum = HomeResFile(handle);
RemoveResource(handle);
ThrowIfResError();
if (refNum != -1)
UpdateResFile(refNum);
DisposeHandle(handle);
}
}
//---------------------------------------------------------------
//
// DeleteResource (ResType, string)
//
//---------------------------------------------------------------
void DeleteResource(ResType type, const string& name)
{
Handle handle = GetResourceNoLoad(type, name, true);
ASSERT(handle != nil);
if (handle != nil) {
short refNum = HomeResFile(handle);
RemoveResource(handle);
ThrowIfResError();
if (refNum != -1)
UpdateResFile(refNum);
DisposeHandle(handle);
}
}
//---------------------------------------------------------------
//
// Has1Resource (ResType, ResID)
//
//---------------------------------------------------------------
bool Has1Resource(ResType type, ResID id)
{
SLDisable();
Handle rsrc = GetResourceNoLoad(type, id, true);
bool has = rsrc != nil;
ReleaseResource(rsrc);
SLEnable();
return has;
}
//---------------------------------------------------------------
//
// Has1Resource (ResType, string)
//
//---------------------------------------------------------------
bool Has1Resource(ResType type, const string& name)
{
SLDisable();
Handle rsrc = GetResourceNoLoad(type, name, true);
bool has = rsrc != nil;
ReleaseResource(rsrc);
SLEnable();
return has;
}
//---------------------------------------------------------------
//
// HasResource (ResType, ResID)
//
//---------------------------------------------------------------
bool HasResource(ResType type, ResID id)
{
SLDisable();
Handle rsrc = GetResourceNoLoad(type, id, false);
bool has = rsrc != nil;
ReleaseResource(rsrc);
SLEnable();
return has;
}
//---------------------------------------------------------------
//
// HasResource (ResType, string)
//
//---------------------------------------------------------------
bool HasResource(ResType type, const string& name)
{
SLDisable();
Handle rsrc = GetResourceNoLoad(type, name, false);
bool has = rsrc != nil;
ReleaseResource(rsrc);
SLEnable();
return has;
}
//---------------------------------------------------------------
//
// ChangeResourceName
//
//---------------------------------------------------------------
void ChangeResourceName(Handle handle, const string& name)
{
short id;
ResType type;
Str255 currentName;
GetResInfo(handle, &id, &type, currentName);
ThrowIfResError();
if (name != PStrToStr(currentName)) {
SetResInfo(handle, id, StrToPStr(name));
ThrowIfResError();
}
}
//---------------------------------------------------------------
//
// ReleaseIfResource
//
//---------------------------------------------------------------
Handle ReleaseIfResource(Handle handle)
{
if (handle != nil) {
ASSERT(IsResourceHand(handle));
ReleaseResource(handle);
}
return nil;
}
//---------------------------------------------------------------
//
// GetResourceInfo
//
//---------------------------------------------------------------
SResourceInfo GetResourceInfo(Handle hand)
{
short id;
ResType type;
Str255 name;
GetResInfo(hand, &id, &type, name);
ThrowIfResError();
return SResourceInfo(type, id, PStrToStr(name));
}
#pragma mark -
// ===================================================================================
// class TOpenResFile
// ===================================================================================
//---------------------------------------------------------------
//
// TOpenResFile::~TOpenResFile
//
//---------------------------------------------------------------
TOpenResFile::~TOpenResFile()
{
if (mRefNum != -1 && mRefNum != 0) // zero closes all open resource files!
CloseResFile(mRefNum);
}
//---------------------------------------------------------------
//
// TOpenResFile::TOpenResFile
//
//---------------------------------------------------------------
TOpenResFile::TOpenResFile(const FSSpec& spec, SignedByte permission)
{
SLDisable();
mRefNum = FSpOpenResFile(&spec, permission);
OSErr err = ResError();
SLEnable();
if (err == eofErr) {
FInfo info;
OSErr err = HGetFInfo(spec.vRefNum, spec.parID, spec.name, &info);
ThrowIfOSErr(err);
FSpCreateResFile(&spec, info.fdCreator, info.fdType, smSystemScript);
ThrowIfResError();
mRefNum = FSpOpenResFile(&spec, permission);
ThrowIfResError();
} else
ThrowIfOSErr(err);
}
#pragma mark -
// ===================================================================================
// class TSaveResFile
// ===================================================================================
//---------------------------------------------------------------
//
// TSaveResFile::~TSaveResFile
//
//---------------------------------------------------------------
#pragma segment ZTools
TSaveResFile::~TSaveResFile()
{
UseResFile(mSavedResFile);
}
//---------------------------------------------------------------
//
// TSaveResFile::TSaveResFile ()
//
//---------------------------------------------------------------
#pragma segment ZTools
TSaveResFile::TSaveResFile()
{
mSavedResFile = CurResFile();
}
//---------------------------------------------------------------
//
// TSaveResFile::TSaveResFile (short)
//
//---------------------------------------------------------------
TSaveResFile::TSaveResFile(short newResFile)
{
mSavedResFile = CurResFile();
if (newResFile != kNoFileRefNum) {
UseResFile(newResFile);
ThrowIfResError();
}
}
#pragma mark -
// ===================================================================================
// class TNoResLoad
// ===================================================================================
//---------------------------------------------------------------
//
// TNoResLoad::~TNoResLoad
//
//---------------------------------------------------------------
TNoResLoad::~TNoResLoad()
{
if (mDisabled)
SetResLoad(true);
}
//---------------------------------------------------------------
//
// TNoResLoad::TNoResLoad
//
//---------------------------------------------------------------
TNoResLoad::TNoResLoad()
{
mDisabled = LMGetResLoad() != 0;
if (mDisabled)
SetResLoad(false);
}